package com.acmen.easyapi.parse;

import com.acmen.easyapi.annotation.Param;
import com.acmen.easyapi.annotation.ResParam;
import com.acmen.easyapi.generator.DataGenerator;
import com.acmen.easyapi.generator.DataGeneratorFactory;
import com.acmen.easyapi.model.ResParamNode;
import com.acmen.easyapi.strategy.ResParamStrategy;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.acmen.easyapi.model.ParamNode;
import com.acmen.easyapi.util.ClassUtil;
import com.acmen.easyapi.util.DictionaryUtil;
import com.acmen.easyapi.util.StringUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.*;


/**
 * 接口详细说明表格工具
 *
 * @author acmen
 */
@Component
public class ResponseParser extends ParamParser {
    private Map<String,List<ParamNode>> paramNodeMap = new HashMap<>();
    @Resource
    private DataGeneratorFactory dataGeneratorFactory;
    @Resource
    private ResParamStrategy resParamStrategy;


    public ResParamNode createParamNode(Method method) {
        paramNodeMap.clear();
        ResParamNode rootNode = new ResParamNode();
        rootNode.setName("response");
        rootNode.setLabel("根节点");
        List<ResParamNode> subNodes = (List)createParamNodes(method.getGenericReturnType(), new HashMap<>());
        rootNode.setSubNodes(subNodes);
        return rootNode;
    }

    @Override
    protected List<ParamNode> createNodesForClass(Class clazz, Map<TypeVariable, Type> typeMap) {
               List<ParamNode> paramNodes = new ArrayList<>();
        // 判断是否为基本类型
        if(ClassUtil.isBasicType(clazz)){
            return paramNodes;
        }
        // 获取所有字段
        List<Field> fields = ClassUtil.getFields(clazz);
        // 如果字段为空，则返回空的paramNodes列表
        if (fields.isEmpty()) {
            return paramNodes;
        }
        // 键为clazz的类名
        String key = clazz.getName();
        // 如果paramNodeMap中已经存在key，则从JSON字符串中解析为ParamNode对象并返回
        if(paramNodeMap.containsKey(key)){
            List<ParamNode> paramNodes_ = JSON.parseArray(JSON.toJSONString(paramNodeMap.get(key)),ParamNode.class);
            // 返回新对象
            return paramNodes_;
        }
        // 遍历所有字段
        for (Field field : fields) {
            // 创建ResParamNode对象
            ResParamNode paramNode = new ResParamNode();
            // 获取JSONField注解
            JSONField jsonField = ClassUtil.getAnnotation(field, JSONField.class);
            // 如果jsonField存在且serialize为false，则跳过（不序列化）
            if(jsonField!=null&&!jsonField.serialize()){
                continue;
            }
            // 获取Param对象
            Param param = resParamStrategy.getParam(clazz,field);
            // 如果param为空，则跳过
            if(param == null){
                continue;
            }
            // 获取目标类型
            Type fieldType = getTargetType(field.getGenericType(), typeMap);
            // 判断是否为数组
            if(fieldType!=null){
                paramNode.setArray(isArrayType(fieldType));
            }else{
                paramNode.setArray(isArrayType(field.getType()));
            }
            // 设置字段名
            paramNode.setName(field.getName());
            // 设置字段（节点）描述
            paramNode.setLabel(param.label());

            // 设置字段类型
            paramNode.setType(field.getGenericType().getTypeName());
            // 获取数据类型别名
            String typeAlias = getDataTypeAlias(field.getGenericType(), typeMap);
            paramNode.setTypeAlias(typeAlias);
            // 获取ResParam对象
            ResParam resParam = resParamStrategy.getResParam(clazz,field);
            // 如果resParam不为空，则设置Client属性
            if(resParam != null){
                paramNode.setClient(resParam.client());
            }
            // 如果param的note不为空，则添加到paramNode的注释中
            if(StringUtil.isNotEmpty(param.note())){
                paramNode.addNote(param.note());
            }
            // 如果param的dictType不为空，则设置Dictionaries属性
            if(StringUtil.isNotEmpty(param.dictType())){
                paramNode.setDictType(param.dictType());
            // 如果field的类型是枚举类型，则获取对应的字典列表
            }else if (field.getType().isEnum() ) {
                paramNode.setDictionaries(DictionaryUtil.getDictsFromEnum2(field.getType()));
            // 如果param的enumClass是枚举类型，则获取对应的字典列表
            }else if(param.enumClass().isEnum()){
                paramNode.setDictionaries(DictionaryUtil.getDictsFromEnum(param.enumClass()));
            }
            // 如果param的example不为空，则设置Example属性
            if(StringUtil.isNotEmpty(param.example())){
                paramNode.setExample(param.example());
            // 否则生成随机数据并设置为Example2属性
            }else{
                DataGenerator dataGenerator = dataGeneratorFactory.getDataGenerator(field, param);
                if (dataGenerator != null) {
                    Object randomData = dataGenerator.generate(field, param);
                    paramNode.setExample2(randomData);
                }
            }
            // 将paramNode添加到paramNodes列表中
            paramNodes.add(paramNode);
        }
        // 将paramNodes添加到paramNodeMap中
        paramNodeMap.put(key, paramNodes);

        // 遍历所有字段
        for (Field field : fields) {
            // 过滤出字段名相同且不是基本类型的paramNode
            Optional<ParamNode> optional = paramNodes.stream().filter(x->StringUtil.equals(x.getName(),field.getName())).findFirst();
            // 如果不存在则跳过
            if(!optional.isPresent()){
                continue;
            }
            // 如果field的类型是基本类型，则跳过
            if(ClassUtil.isBasicType(field.getClass())){
                continue;
            }
            // 获取paramNode
            ResParamNode paramNode = (ResParamNode)optional.get();
            // 递归创建子节点paramNodes
            List<ParamNode> subNodes = createParamNodes(field.getGenericType(), typeMap);
            // 如果子节点不为空
            if(!subNodes.isEmpty()){
                // 过滤出paramNode中子节点名与field的字段名相同的部分
                Optional<ParamNode> opt = subNodes.stream().filter(x->StringUtil.equals(x.getName(),paramNode.getName())).findFirst();
                // 如果存在则更新paramNode的子节点为subNodes
                if(opt.isPresent()){
                    ParamNode rpn = opt.get();
                    rpn.setName(rpn.getName()+"(树)");
                }
                // 设置paramNode的子节点为subNodes
                paramNode.setSubNodes((List)subNodes);
            }
        }
        return paramNodes;
    }
}
